package com.supermap.extend.trafficanalyst;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.supermap.analyst.networkanalyst.*;
import com.supermap.analyst.spatialanalyst.ComputeDistanceResult;
import com.supermap.analyst.spatialanalyst.ProximityAnalyst;
import com.supermap.data.*;

import java.util.*;
import java.util.stream.Collectors;

public class TrafficAnalyst {

    private static DatasetVector m_datasetVectorRoadJunction;
    private static DatasetVector m_datasetVectorRoadNetwork;
    private static DatasetVector m_datasetVectorRoadLink;
    private static DatasetVector m_datasetVectorRoadNetwork_Node;

    public static boolean initData(String udbxFilePath){

        Workspace workspace = new Workspace();
        DatasourceConnectionInfo connectionInfo = new DatasourceConnectionInfo();
        connectionInfo.setEngineType(EngineType.UDBX);
        connectionInfo.setServer(udbxFilePath);

        Datasource datasource = workspace.getDatasources().open(connectionInfo);

        if (datasource.isOpened()){
            m_datasetVectorRoadJunction = (DatasetVector)datasource.getDatasets().get("RoadJunction");
            m_datasetVectorRoadNetwork = (DatasetVector)datasource.getDatasets().get("RoadNetwork");
            m_datasetVectorRoadNetwork_Node = (DatasetVector)datasource.getDatasets().get("RoadNetwork_Node");
            m_datasetVectorRoadLink = (DatasetVector)datasource.getDatasets().get("RoadLink");
            return true;
        }else {
            return false;
        }
    }

    /**
     * 参数检查
     * @param params 接口传入参数
     * @return 检查结果，通过返回true，失败返回false
     */
    private boolean checkNotNull(Object... params) {
        for (Object param : params) {
            if (param == null) {
                return true;
            }
        }
        return false;
    }

    /**
     * 通过点位和范围，查询最近路口及路口方向
     * @param geoPoint 查询点位
     * @param distance 查询范围
     * @return 最近路口id、路口方向
     */
    public JSONObject junctionQuery(GeoPoint geoPoint, double distance){

        JSONObject jsonObjectResult = new JSONObject();

        if (checkNotNull(geoPoint, distance)){
            jsonObjectResult.put("success",false);
            jsonObjectResult.put("error","Please check the parameters");
            return jsonObjectResult;
        }

        Recordset recordset = m_datasetVectorRoadJunction.getRecordset(false, CursorType.DYNAMIC);

        Geometry[] geometries = new Geometry[1];
        geometries[0] = geoPoint;

        ComputeDistanceResult[] computeDistanceResult = ProximityAnalyst.computeMinDistance(geometries,recordset,0,distance);

        int[] a = computeDistanceResult[0].getReferenceGeometryIDs();
        String par = "SmID="+a[0];
        QueryParameter parameter = new QueryParameter();
        parameter.setAttributeFilter(par);
        parameter.setCursorType(CursorType.STATIC);
        parameter.setSpatialQueryMode(SpatialQueryMode.NONE);
        Recordset result = m_datasetVectorRoadJunction.query(parameter);

        String junction_directions = (String)result.getFieldValue("junction_directions");
        String[] strArray = junction_directions.split(",");
        JSONArray jsonArray_junction_directions = new JSONArray();
        jsonArray_junction_directions.addAll(Arrays.asList(strArray));

        String junction_id = (String)result.getFieldValue("junction_id");

        jsonObjectResult.put("success",true);
        jsonObjectResult.put("junction_id",junction_id);
        jsonObjectResult.put("junction_directions",jsonArray_junction_directions);

        return jsonObjectResult;
    }

    /**
     * 通过点位和范围，查询最近的道路、方向、以及点位到道路的垂点
     * @param geoPoint 查询点位
     * @param distance 查询范围
     * @return 路段id、路段点位节点、路段方向、查询点位到路段的垂点
     */
    public JSONObject linkQuery(GeoPoint geoPoint,double distance){
        JSONObject jsonObjectResult = new JSONObject();
        if (checkNotNull(geoPoint, distance)){
            jsonObjectResult.put("success",false);
            jsonObjectResult.put("error","Please check the parameters");
            return jsonObjectResult;
        }

        Recordset recordset = m_datasetVectorRoadLink.getRecordset(false, CursorType.DYNAMIC);
        Geometry[] geometries = new Geometry[1];
        geometries[0] = geoPoint;

        ComputeDistanceResult[] computeDistanceResult = ProximityAnalyst.computeMinDistance(geometries,recordset,0,distance);
        int[] a = computeDistanceResult[0].getReferenceGeometryIDs();
        String par = "SmID="+a[0];
        QueryParameter parameter = new QueryParameter();
        parameter.setAttributeFilter(par);
        parameter.setCursorType(CursorType.STATIC);
        parameter.setSpatialQueryMode(SpatialQueryMode.NONE);
        Recordset result = m_datasetVectorRoadLink.query(parameter);

        String link_id = (String)result.getFieldValue("link_id");

        GeoLine geoLine = (GeoLine) result.getGeometry();
        JSONArray jsonArrayGeoLine = Tool.geoLineToJsonArray(geoLine);

        String link_direction = (String)result.getFieldValue("link_direction");
        String[] strArray = link_direction.split(",");
        JSONArray jsonArray_link_direction = new JSONArray();
        jsonArray_link_direction.addAll(Arrays.asList(strArray));

        Point2D pramPoint2D = new Point2D(geoPoint.getX(),geoPoint.getY());

        for ( int i = 0; i < geoLine.getPartCount(); i++ ){
            Point2D[] point2DS = geoLine.getPart(i).toArray();
            for ( int j = 0; j<point2DS.length-1; j++){

                Point2D startPoint = point2DS[j];
                Point2D endPoint = point2DS[j+1];
                Point2D perpendicularPoint = Geometrist.computePerpendicularPosition(pramPoint2D,startPoint,endPoint);

                if (Geometrist.isPointOnLine(perpendicularPoint,startPoint,endPoint,false)){
                    JSONObject jsonObjectPerpendicularPoint = new JSONObject();
                    jsonObjectPerpendicularPoint.put("x",perpendicularPoint.getX());
                    jsonObjectPerpendicularPoint.put("y",perpendicularPoint.getY());
                    jsonObjectResult.put("perpendicularPoint",jsonObjectPerpendicularPoint);
                }
            }
        }
        jsonObjectResult.put("link_direction",jsonArray_link_direction);
        jsonObjectResult.put("geometry",jsonArrayGeoLine);
        jsonObjectResult.put("link_id",link_id);
        jsonObjectResult.put("success",true);
        return jsonObjectResult;
    }

    /**
     * 通过路口id，道路方向，查找上一个路口
     * @param junction_id 路口id
     * @param link_direction 道路方向
     * @return 上一个路口id
     */
    public JSONObject queryPreviousJunction(String junction_id,String link_direction){

        JSONObject jsonObjectResult = new JSONObject();

        if (checkNotNull(junction_id,link_direction)){
            jsonObjectResult.put("success",false);
            jsonObjectResult.put("error","Please check the parameters");
            return jsonObjectResult;
        }

        // 根据路口id，查询对应路口
        String par = "junction_id=\""+junction_id+"\"";
        QueryParameter parameter = new QueryParameter();
        parameter.setAttributeFilter(par);
        parameter.setCursorType(CursorType.STATIC);
        parameter.setSpatialQueryMode(SpatialQueryMode.NONE);
        Recordset par_junction = m_datasetVectorRoadJunction.query(parameter);

        // 根据路口及方向，查出对应路段
        String[] incoming_links = par_junction.getString("incoming_links").split(",");
        String link_id = null;
        for (String incoming_link : incoming_links) {
            if (incoming_link.isEmpty()) {
                continue;
            }
            String[] parts = incoming_link.split("\\|");
            if (parts[1].equals(link_direction)){
                link_id = parts[0];
            }
        }

        //根据路段，递归查询上一个路口
        HashSet<String> visitedLinks = new HashSet<>();
        jsonObjectResult.put("link_id",queryPreviousJunction(m_datasetVectorRoadLink,link_id, visitedLinks));
        jsonObjectResult.put("success",true);
        return jsonObjectResult;
    }

    /**
     * 根据路段，递归查询上一个路口
     */
    private String queryPreviousJunction(DatasetVector linkDatasetVector,String link_id, Set<String> visitedLinks){

        // 1. 检查是否已访问过（避免重复查询某节点）
        if (visitedLinks.contains(link_id)) {
            return null;
        }
        visitedLinks.add(link_id);
        Recordset recordsetResult = null;

        try {
            // 根据路段查是否包含FromRoadJunction ,
            String par = "link_id='"+link_id+"'";
            QueryParameter parameter = new QueryParameter();
            parameter.setAttributeFilter(par);
            parameter.setCursorType(CursorType.STATIC);
            parameter.setSpatialQueryMode(SpatialQueryMode.NONE);
            recordsetResult = linkDatasetVector.query(parameter);

            String road_junction = recordsetResult.getString("from_junction_id");
            if (road_junction!=null && !road_junction.isEmpty()){
                return road_junction;
            }

            // 不包含的话，继续通过incoming_link_ids继续查找路段id，并递归
            String incoming_link_id  = recordsetResult.getString("incoming_link_ids");
            if (incoming_link_id != null ) {
                String[] link_ids = Arrays.stream(incoming_link_id.split(","))
                        .filter(s -> s != null && !s.trim().isEmpty())
                        .toArray(String[]::new);
                for (String linkId : link_ids) {
                    String result = queryPreviousJunction(linkDatasetVector,linkId,visitedLinks);
                    if( result != null){
                        return result;
                    }
                }

            }
        } finally {
            if (recordsetResult != null) {
                recordsetResult.close();
            }
        }
        return null;
    }

    /**
     * 最佳路径分析
     * @param point2Ds 点位
     * @return 经过的路口id、道路点串、道路id
     */
    public JSONObject findPath(Point2Ds point2Ds){

        JSONObject jsonObjectResult = new JSONObject();

        if (checkNotNull(point2Ds)){
            jsonObjectResult.put("success",false);
            jsonObjectResult.put("error","Please check the parameters");
            return jsonObjectResult;
        }

        TransportationAnalystSetting transportationAnalystSetting = new TransportationAnalystSetting();
        transportationAnalystSetting.setNetworkDataset(m_datasetVectorRoadNetwork);
        transportationAnalystSetting.setEdgeIDField ( "SmEdgeID");
        transportationAnalystSetting.setNodeIDField ( "SmNodeID");
        transportationAnalystSetting.setFNodeIDField ("SmFNode");
        transportationAnalystSetting.setTNodeIDField ( "SmTNode");
        WeightFieldInfo weightInfo = new WeightFieldInfo();
        weightInfo.setFTWeightField ( "SmLength");
        weightInfo.setTFWeightField ( "SmLength");
        transportationAnalystSetting.getWeightFieldInfos().add(weightInfo);

        TransportationAnalystParameter transportationAnalystParameter = new TransportationAnalystParameter();
        transportationAnalystParameter.setPathGuidesReturn(true);
        transportationAnalystParameter.setRoutesReturn(true);
        transportationAnalystParameter.setEdgesReturn(true);
        transportationAnalystParameter.setNodesReturn(true);
        transportationAnalystParameter.setWeightName("length");
        transportationAnalystParameter.setPoints(point2Ds);

        TransportationAnalyst transportationAnalyst= new TransportationAnalyst();
        transportationAnalyst.setAnalystSetting(transportationAnalystSetting);
        transportationAnalyst.load();

        TransportationAnalystResult transportationAnalystResult = transportationAnalyst.findPath(transportationAnalystParameter, false);

        GeoLine geoLine = transportationAnalystResult.getRoutes()[0].convertToLine();
        JSONArray jsonArrayGeometry = Tool.geoLineToJsonArray(geoLine);
        int[] resultEdges = transportationAnalystResult.getEdges()[0];

        //根据 Edges 查 linkID
        String[] link_ids = new String[resultEdges.length];
        for (int i = 0 ; i <resultEdges.length; i++){
            String par = "SmID="+resultEdges[i];
            QueryParameter parameter = new QueryParameter();
            parameter.setAttributeFilter(par);
            parameter.setCursorType(CursorType.STATIC);
            parameter.setSpatialQueryMode(SpatialQueryMode.NONE);
            link_ids[i] = m_datasetVectorRoadLink.query(parameter).getString("link_id");
        }

        //根据 Node(smid) 查 junction_id
        int[] resultNodes = transportationAnalystResult.getNodes()[0];
        String[] junction_ids = new String[resultNodes.length];
        for ( int j = 0; j<resultNodes.length ; j++){
            String par = "smid="+resultNodes[j];
            QueryParameter parameter = new QueryParameter();
            parameter.setAttributeFilter(par);
            parameter.setCursorType(CursorType.STATIC);
            parameter.setSpatialQueryMode(SpatialQueryMode.NONE);
            junction_ids[j] = m_datasetVectorRoadNetwork_Node.query(parameter).getString("junction_id");
        }

        String[] roadJunctions_filter = Arrays.stream(junction_ids)
                .filter(str -> str != null && !str.isEmpty())
                .distinct()
                .toArray(String[]::new);

        jsonObjectResult.put("success",true);
        jsonObjectResult.put("geometry",jsonArrayGeometry);
        jsonObjectResult.put("link_ids",link_ids);
        jsonObjectResult.put("roadJunctions",roadJunctions_filter);
        return jsonObjectResult;
    }

    /**
     * 通过路口id、上下游方向、道路间隔（和该路口相隔为n的路段上符合方向的路口）三个要素查找对应路口
     * @param junction_id 路口id
     * @param link_direction 上下游方向
     * @param gap 道路间隔
     * @return 路口id
     */
    public JSONObject queryPreviousJunctionByGap(String junction_id,String link_direction,int gap){

        JSONObject jsonObjectResult = new JSONObject();

        if (checkNotNull(junction_id,link_direction,gap)){
            jsonObjectResult.put("success",false);
            jsonObjectResult.put("error","Please check the parameters");
            return jsonObjectResult;
        }

        //根据junction_id查找对应路口
        String par = "junction_id=\""+junction_id+"\"";
        QueryParameter parameter = new QueryParameter();
        parameter.setAttributeFilter(par);
        parameter.setCursorType(CursorType.STATIC);
        parameter.setSpatialQueryMode(SpatialQueryMode.NONE);
        Recordset par_junction = m_datasetVectorRoadJunction.query(parameter);

        //根据路口和方向查找首段道路
        String first_links = null;
        String[] link_ids_first = null;
        if( link_direction.equals("upstream")){
            first_links  = par_junction.getString("incoming_links");
        }else if (link_direction.equals("downstream")){
            first_links  = par_junction.getString("outgoing_links");
        }
        if (first_links != null ) {
            link_ids_first = Arrays.stream(first_links.split(","))
                    .filter(s -> s != null && !s.trim().isEmpty())
                    .map(s -> {
                        int pipeIndex = s.indexOf('|');
                        return pipeIndex != -1 ? s.substring(0, pipeIndex) : s;
                    })
                    .toArray(String[]::new);
        }

        Map<String, ArrayList<String>> link_id_map = new HashMap<>();

        //将首段道路id添加到map中
        link_id_map.put("gap1",Tool.stringsToArrayList(link_ids_first));

        String queryLinkPar = null;
        if (gap > 1){
            //gap>1,存在二叉树查询,根据方向确定二叉树查询参数
            if( link_direction.equals("upstream")){
                queryLinkPar = "incoming_link_ids";
            }else if (link_direction.equals("downstream")){
                queryLinkPar = "outgoing_link_ids";
            }
        }

        for ( int i = 2; i < gap+1; i++){
            link_id_map.put("gap" + i, new ArrayList<String>());
            //根据第i-1级的所有linkId，查出第i级的所有linkId
            queryPreviousJunctionByGap(m_datasetVectorRoadLink,link_id_map,queryLinkPar,i);
        }

        //根据方向确定查询路口参数
        String queryJunctionPar = null;
        if( link_direction.equals("upstream")){
            queryJunctionPar = "from_junction_id";
        }else if (link_direction.equals("downstream")){
            queryJunctionPar = "to_junction_id";
        }

        List<Object> result = new ArrayList<>();
        //根据第gap级的所有道路，查询所属的路口id
        for (String link_id : link_id_map.get("gap"+gap)){
            String junctionPar = "link_id=\""+link_id+"\"";
            parameter.setAttributeFilter(junctionPar);
            Recordset recordset = m_datasetVectorRoadLink.query(parameter);
            String result_junctionID = recordset.getString(queryJunctionPar);
            if (result_junctionID != null && !result_junctionID.isEmpty()){
                result.add(result_junctionID);
            }
        }
        jsonObjectResult.put("success",true);
        jsonObjectResult.put("junction_id",result.stream().distinct().collect(Collectors.toList()));
        return jsonObjectResult;
    }

    private void queryPreviousJunctionByGap(DatasetVector linkDatasetVector,Map<String, ArrayList<String>> link_id_map,String queryLinkPar,int i){

        QueryParameter link_id_parameter = new QueryParameter();
        link_id_parameter.setCursorType(CursorType.STATIC);
        link_id_parameter.setSpatialQueryMode(SpatialQueryMode.NONE);

        //获取第i-1级linkID
        ArrayList<String> link_id = link_id_map.get("gap"+(i-1));

        //获取第i级linkID
        ArrayList<String> link_id_now = link_id_map.get("gap"+i);

        for (String value : link_id) {

            String Par = "link_id=\"" + value + "\"";
            link_id_parameter.setAttributeFilter(Par);
            String links = linkDatasetVector.query(link_id_parameter).getString(queryLinkPar);
            String[] link_ids = Arrays.stream(links.split(","))
                    .filter(s -> s != null && !s.trim().isEmpty())
                    .map(s -> {
                        int pipeIndex = s.indexOf('|');
                        return pipeIndex != -1 ? s.substring(0, pipeIndex) : s;
                    })
                    .toArray(String[]::new);
            for (String s : link_ids) {
                if (s != null) {
                    link_id_now.add(s);
                }
            }
        }
        link_id_map.put("gap"+i,link_id_now);
    }

    /**
     * 通过绘制面，查询与面相交的所有边界道路，以及道路上在边界内的路口
     * @param geoRegion 面对象
     * @return 边界道路及对应路口
     */
    public JSONObject queryJunctionByRegionBoundary(GeoRegion geoRegion){

        JSONObject jsonObjectResult = new JSONObject();

        if (checkNotNull(geoRegion)){
            jsonObjectResult.put("success",false);
            jsonObjectResult.put("error","Please check the parameters");
            return jsonObjectResult;
        }

        //计算在面内的所有路口数据
        ArrayList<String> junction = new ArrayList<>();

        Recordset roadJunctionRecordset = m_datasetVectorRoadJunction.query(geoRegion,0,CursorType.DYNAMIC);
        for (int j = 0; j< roadJunctionRecordset.getRecordCount(); j++){
            junction.add(roadJunctionRecordset.getString("junction_id"));
        }

        Recordset recordset = m_datasetVectorRoadLink.getRecordset(false,CursorType.STATIC);

        JSONArray jsonArray = new JSONArray();
        for (int i=0 ; i<recordset.getRecordCount(); i++){
            Geometry geometry = recordset.getGeometry();
            if (Geometrist.hasCross(geometry,geoRegion)){
                String from_junction_id = recordset.getString("from_junction_id");
                String to_junction_id = recordset.getString("to_junction_id");

                if (from_junction_id != null && !from_junction_id.isEmpty()
                        && junction.contains(from_junction_id)) {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("junction_id",from_junction_id);
                    jsonObject.put("link_id",recordset.getString("link_id"));
                    jsonArray.add(jsonObject);
                }
                if (to_junction_id != null && !to_junction_id.isEmpty()
                        && junction.contains(to_junction_id)) {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("junction_id",to_junction_id);
                    jsonObject.put("link_id",recordset.getString("link_id"));
                    jsonArray.add(jsonObject);
                }
            }
            recordset.moveNext();
        }

        jsonObjectResult.put("success",true);
        jsonObjectResult.put("data",jsonArray);
        return jsonObjectResult;
    }

    /**
     * 查询出指定路口之间n条路径（n不大于10）
     * @param junction_ids 路口id数组
     * @param num 路径数量（不大于10）
     * @return json
     */
    public JSONObject findPathByNum(String[] junction_ids, int num){

        JSONObject jsonObjectResult = new JSONObject();
        JSONArray jsonArrayPlan = new JSONArray();

        if (checkNotNull(junction_ids,num)){
            jsonObjectResult.put("success",false);
            jsonObjectResult.put("error","Please check the parameters");
            return jsonObjectResult;
        }

        TransportationAnalystSetting transportationAnalystSetting = new TransportationAnalystSetting();
        transportationAnalystSetting.setNetworkDataset(m_datasetVectorRoadNetwork);
        transportationAnalystSetting.setEdgeIDField ( "SmEdgeID");
        transportationAnalystSetting.setNodeIDField ( "SmNodeID");
        transportationAnalystSetting.setFNodeIDField ("SmFNode");
        transportationAnalystSetting.setTNodeIDField ( "SmTNode");
        WeightFieldInfo weightInfo = new WeightFieldInfo();
        weightInfo.setFTWeightField ( "SmLength");
        weightInfo.setTFWeightField ( "SmLength");
        transportationAnalystSetting.getWeightFieldInfos().add(weightInfo);

        TransportationAnalystParameter transportationAnalystParameter = new TransportationAnalystParameter();
        transportationAnalystParameter.setPathGuidesReturn(true);
        transportationAnalystParameter.setRoutesReturn(true);
        transportationAnalystParameter.setEdgesReturn(true);
        transportationAnalystParameter.setNodesReturn(true);
        transportationAnalystParameter.setWeightName("length");

        //起终点和途径点获取
        Point2Ds point2Ds = junctionIDsToPoints(junction_ids,m_datasetVectorRoadJunction);
        transportationAnalystParameter.setPoints(point2Ds);

        TransportationAnalyst transportationAnalyst= new TransportationAnalyst();
        transportationAnalyst.setAnalystSetting(transportationAnalystSetting);
        transportationAnalyst.load();

        //分析次数
        int analystNum = Math.min(num,10);

        //所有分析结果的弧段集合
        int[][] allBarrierEdges = new int[analystNum][];

        //关键(必经)弧段集合
        Set<Integer> criticalEdgeSet = null;

        try {
            for (int i=0; i<analystNum; i++ ){
                //设置障碍点集合
                int[] barrierEdges = new int[i];
                for (int j=0 ; j<i;j++){

                    int[] edges = allBarrierEdges[j];
                    int selectedEdge = -1;

                    if (criticalEdgeSet == null){
                        int randomIndex = new Random().nextInt(edges.length);
                        selectedEdge = edges[randomIndex];
                    }else {
                        for (int edge : edges){
                            if (!criticalEdgeSet.contains(edge)) {
                                selectedEdge = edge;
                                break;
                            }
                        }
                    }
                    if (selectedEdge == -1) {
                        throw new RuntimeException("无法找到非关键边！");
                    }
                    barrierEdges[j] = selectedEdge;
                }
                transportationAnalystParameter.setBarrierEdges(barrierEdges);
                TransportationAnalystResult transportationAnalystResult = transportationAnalyst.findPath(transportationAnalystParameter, true);

                GeoLine geoLine = transportationAnalystResult.getRoutes()[0].convertToLine();
                JSONArray jsonArrayGeometry = Tool.geoLineToJsonArray(geoLine);

                int[] resultEdges = transportationAnalystResult.getEdges()[0];
                int[] resultNodes = transportationAnalystResult.getNodes()[0];

                if (i==0 && resultEdges!=null ){
                    int[] criticalEdges = transportationAnalyst.findCriticalEdges(resultEdges[0],resultEdges[resultEdges.length-1]);
                    criticalEdgeSet = (criticalEdges != null)
                            ? Arrays.stream(criticalEdges).boxed().collect(Collectors.toSet())
                            : Collections.emptySet();
                }

                allBarrierEdges[i] = resultEdges;

                //根据 EdgeID(smid) 查 linkID
                String[] linkIDs = new String[resultEdges.length];
                for (int k = 0 ; k <resultEdges.length; k++){
                    String par = "SmID="+resultEdges[k];
                    QueryParameter parameter = new QueryParameter();
                    parameter.setAttributeFilter(par);
                    parameter.setCursorType(CursorType.STATIC);
                    parameter.setSpatialQueryMode(SpatialQueryMode.NONE);
                    linkIDs[k] = m_datasetVectorRoadLink.query(parameter).getString("link_id");
                }

                //根据 Node(smid) 查 junction_id
                String[] junctionIDs = new String[resultNodes.length];
                for ( int j = 0; j<resultNodes.length ; j++){
                    String par = "smid="+resultNodes[j];
                    QueryParameter parameter = new QueryParameter();
                    parameter.setAttributeFilter(par);
                    parameter.setCursorType(CursorType.STATIC);
                    parameter.setSpatialQueryMode(SpatialQueryMode.NONE);
                    junctionIDs[j] = m_datasetVectorRoadNetwork_Node.query(parameter).getString("junction_id");
                }

                String[] junctionIDs_filter = Arrays.stream(junctionIDs)
                        .filter(str -> str != null && !str.isEmpty())
                        .distinct()
                        .toArray(String[]::new);

                JSONObject jsonObject = new JSONObject();
                jsonObject.put("geometry",jsonArrayGeometry);
                jsonObject.put("linkIDs",linkIDs);
                jsonObject.put("junctionIDs",junctionIDs_filter);
                jsonObject.put("plan",i+1);
                jsonArrayPlan.add(jsonObject);

            }
        }catch (Exception e){
            throw new RuntimeException("分析异常终止: " + e.getMessage(), e);
        }

        jsonObjectResult.put("success",true);
        jsonObjectResult.put("data",jsonArrayPlan);

        return jsonObjectResult;
    }

    private Point2Ds junctionIDsToPoints(String[] junction_ids,DatasetVector junctionDatasetVector){

        Point2Ds point2Ds = new Point2Ds();

        QueryParameter parameter = new QueryParameter();
        parameter.setCursorType(CursorType.STATIC);
        parameter.setSpatialQueryMode(SpatialQueryMode.NONE);

        for (int i = 0; i<junction_ids.length; i++){
            String par = "junction_id=\""+junction_ids[i]+"\"";
            parameter.setAttributeFilter(par);
            GeoPoint geoPoint = (GeoPoint)junctionDatasetVector.query(parameter).getGeometry();
            point2Ds.add(new Point2D(geoPoint.getX(),geoPoint.getY()));
        }
        return point2Ds;
    }
}